package com.ww.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

/**
 * 日期处理类
 * @author LJ
 * @date 2015年9月26日 下午5:33:01
 * @version V1.0
 */
public class DateUtils
{
	public final static String DATE_CHINESE_PATTERN = "yyyy年MM月dd日";
	public final static String DATE_PATTERN = "yyyy-MM-dd";
	public final static String DATE_SHORT_PATTERN = "yyyyMMdd";
	public final static String DATE_SLASH_PATTERN = "yyyy/MM/dd";
	public final static String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
	public final static String DATETIME_PATTERN_CREAT_ORDER = "yyyy-MM-dd HH:mm";
	public final static String DATETIME_MILL_SECOND = "yyyy-MM-dd HH:mm:ss.SSS";
	public final static String DATETIME_SHORT_PATTERN = "yyyyMMddHHmmss";
	public final static String MONTH_PATTERN = "yyyy-MM";
	public final static String HOUR_MINUTE = "HH:mm";
	public final static String HOUR_MINUTE_SECOND = "HH:mm:ss";
	public final static long MILLIS_PER_DAY = 24 * DateUtils.MILLIS_PER_HOUR;
	public final static long MILLIS_PER_HOUR = 60 * DateUtils.MILLIS_PER_MINUTE;
	public final static long MILLIS_PER_MINUTE = 60 * DateUtils.MILLIS_PER_SECOND;
	public final static long MILLIS_PER_SECOND = 1000;
	public final static String[] WEEK_NAMES = { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天" };

	/**
	 * 获取当前时间
	 * @return 当前时间
	 */
	public static Date getCurrenDate(String pattern)
	{
		if (pattern != null && "".equals(pattern))
		{
			return convertDate(getTodayStr(), pattern);
		}
		else
		{
			return convertDate(getTodayStr(), DATETIME_PATTERN);
		}
	}

	/**
	 * 获取当前日期
	 */
	public static Date getCurrenDateShort()
	{
		return convertDate(getTodayStr(), DATE_PATTERN);
	}
	
	/**
	 * 获取当前时间戳
	 */
	public static Long getCurrenTimeStamp()
	{
		return  System.currentTimeMillis();
	}

	/**
	 * 在指定日期增加天数
	 * @param date 指定日期
	 * @param days 增加的天数
	 * @return 增加后的日期
	 */
	public static Date addDay(Date date, int days)
	{
		if (days == 0)
		{
			return date;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.DAY_OF_YEAR, days);
		return c.getTime();
	}

	/**
	 * 在指定日期增加月数
	 * @param date 指定日期
	 * @param days 增加的月数
	 * @return 增加后的日期
	 */
	public static Date addMonth(Date date, int days)
	{
		if (days == 0)
		{
			return date;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.DAY_OF_MONTH, days);
		return c.getTime();
	}

	/**
	 * 在指定日期增加小时数
	 * @param date 指定日期
	 * @param hour 增加的小时数
	 * @return 增加后的日期
	 */
	public static Date addHour(Date date, int hour)
	{
		if (hour == 0)
		{
			return date;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.HOUR, hour);
		return c.getTime();
	}

	/**
	 * 获取当前时间
	 * @return 当前时间String
	 */
	public static String getTodayStr()
	{
		String nowString = "";
		String monthString = "";
		String dayString = "";
		String hourString = "";
		String minString = "";
		String secString = "";
		Calendar now = Calendar.getInstance(TimeZone.getTimeZone("GMT+08:00"));
		nowString = nowString + now.get(1) + "-";
		Integer month = now.get(2) + 1;
		if (month < 10)
		{
			monthString = "0" + month;
		}
		else
		{
			monthString = month.toString();
		}

		Integer day = now.get(5);
		if (day < 10)
		{
			dayString = "0" + day;
		}
		else
		{
			dayString = day.toString();
		}
		nowString = nowString + monthString + "-" + dayString;
		Integer hour = now.get(11);
		if (hour < 10)
		{
			hourString = "0" + hour;
		}
		else
		{
			hourString = hour.toString();
		}
		nowString = nowString + " " + hourString;
		Integer min = now.get(12);
		if (min < 10)
		{
			minString = "0" + min;
		}
		else
		{
			minString = min.toString();
		}
		nowString = nowString + ":" + minString;
		Integer sec = now.get(13);
		if (sec < 10)
		{
			secString = "0" + sec;
		}
		else
		{
			secString = sec.toString();
		}
		nowString = nowString + ":" + secString;
		return nowString;
	}

	/**
	 * 获取当前时间Date
	 * @param pattern 转换格式
	 * @return 当前时间Date
	 */
	public static Date getTodayDate(String pattern)
	{
		if (pattern != null && "".equals(pattern))
		{
			return convertDate(getTodayStr(), pattern);
		}
		else
		{
			return convertDate(getTodayStr(), DATETIME_PATTERN);
		}
	}

	/**
	 * 将日期或者时间字符串转换为日期对象
	 * @param date 日期String
	 * @param pattern 转换格式
	 * @return 日期Date
	 */
	public static Date convertDate(String date, String pattern)
	{
		try
		{
			if (StringUtils.isNullString(pattern) || StringUtils.isNullString(date))
			{
				throw new IllegalArgumentException("the date or pattern is empty");
			}
			SimpleDateFormat df = new SimpleDateFormat(pattern.trim());
			return df.parse(date.trim());
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 将日期或者时间戳转化为日期对象
	 * @param date 日期String
	 * @return 日期Date
	 */
	public static Date convertDate(String date)
	{
		if (StringUtils.isNullString(date))
		{
			return null;
		}
		if (date.indexOf(":") > 0)
		{
			return DateUtils.convertDate(date, DATETIME_PATTERN);
		}
		else if (date.indexOf(".") > 0)
		{
			return DateUtils.convertDate(date, DATETIME_MILL_SECOND);
		}
		else
		{
			return DateUtils.convertDate(date, DATE_PATTERN);
		}
	}

	/**
	 * 将日期字符串转换为日期对象
	 * @param str 日期字符串
	 * @return 日期对象
	 * @throws ParseException
	 */
	public static Date getDateFromShortString(String str) throws ParseException
	{
		SimpleDateFormat simpleDF = new SimpleDateFormat("yyyy-MM-dd");
		return simpleDF.parse(str);
	}

	/**
	 * 获取当前时间: 时分秒
	 * @return 日期String
	 */
	public static String getTodayTime()
	{
		return getTodayStr().substring(11);
	}

	/**
	 * 比较两个日期
	 * @param date1 日期date1
	 * @param date2 日期date2
	 * @return date1大于date2返回1 等于返回0 小于返回-1
	 */
	public static int compareDate(Object date1, Object date2)
	{
		if (date1 == null || date2 == null)
		{
			throw new IllegalArgumentException("date1 and date2 must be not null");
		}
		Date d1 = (Date) (date1 instanceof String ? DateUtils.convertDate((String) date1) : date1);
		Date d2 = (Date) (date2 instanceof String ? DateUtils.convertDate((String) date2) : date2);
		return d1.compareTo(d2);
	}

	/**
	 * 获取两个日期相差的分钟数
	 * @param date1 日期date1
	 * @param date2 日期date2
	 * @return 相差的分钟数
	 */
	public static int diffMinute(Date date1, Date date2)
	{
		return (int) ((date1.getTime() - date2.getTime()) / DateUtils.MILLIS_PER_MINUTE);
	}

	/**
	 * 获得两个日期相差天数
	 * @param date1 日期date1
	 * @param date2 日期date2
	 * @return 相差天数
	 */
	public static int diffDate(Date date1, Date date2)
	{
		return (int) ((date1.getTime() - date2.getTime()) / DateUtils.MILLIS_PER_DAY);
	}

	/**
	 * 获得日期相差月数
	 * @param date1 日期date1
	 * @param date2 日期date2
	 * @return 相差月数
	 * @throws ParseException
	 */
	public static int diffMonth(String date1, String date2) throws ParseException
	{
		int result = 0;

		Calendar c1 = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();

		c1.setTime(getDateFromShortString(date1));
		c2.setTime(getDateFromShortString(date2));

		result = c2.get(Calendar.MONDAY) - c1.get(Calendar.MONTH);

		return result == 0 ? 1 : Math.abs(result);
	}

	/**
	 * 按指定格式字符串格式时间
	 * @param date 日期Date
	 * @param pattern 转换格式
	 * @return 日期String
	 */
	public static String formatDate(Date date, String pattern)
	{
		if (StringUtils.isNullString(pattern))
		{
			SimpleDateFormat format = new SimpleDateFormat(DateUtils.DATE_PATTERN);
			return format.format(date);
		}
		else
		{
			SimpleDateFormat format = new SimpleDateFormat(pattern.trim());
			return format.format(date);
		}
	}

	/**
	 * 获取指定时间的小时
	 * @param date 时间Date
	 * @return 小时
	 */
	public static int getHour(Date date)
	{
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.HOUR_OF_DAY);
	}

	/**
	 * 获取指定时间的分钟
	 * @param date 时间Date
	 * @return 分钟
	 */
	public static int getMinute(Date date)
	{
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.MINUTE);
	}

	/**
	 * 获取指定时间的秒
	 * @param date 时间Date
	 * @return 秒
	 */
	public static int getSecond(Date date)
	{
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.SECOND);
	}

	/**
	 * 获取指定日期本周的第一天
	 * @param date 日期Date
	 * @return 日期Date
	 */
	public static Date getFirstDayOfThisWeek(Date date)
	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.setFirstDayOfWeek(Calendar.MONDAY);
		cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
		return cal.getTime();
	}

	/**
	 * 获取指定日期后的多少天
	 * @param date 日期Date
	 * @param n 多少天
	 * @return 日期Date
	 */
	public static Date getNextNDay(Date date, int n)
	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DATE, n);
		return cal.getTime();
	}

	/**
	 * 获取指定日期是星期数
	 * @param date 日期Date
	 * @return 星期数
	 */
	public static int getWeekNumber(Date date)
	{
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		int number = c.get(Calendar.DAY_OF_WEEK) - 1;
		if (number == 0)
		{
			number = 7;
		}
		return number;
	}

	/**
	 * 获取指定日期是星期名称
	 * @param date 日期Date
	 * @return 星期名称
	 */
	public static String getWeekNumberString(Date date)
	{
		int dayNum = DateUtils.getWeekNumber(date);
		return DateUtils.WEEK_NAMES[dayNum - 1];
	}

	/**
	 * 两个日期是否是同一天
	 * @param date1 日期Date
	 * @param date2 日期Date
	 * @return 是/否
	 */
	public static boolean isSameDay(Object date1, Object date2)
	{
		return DateUtils.compareDate(date1, date2) == 0;
	}

	/**
	 * 验证日期是否合法
	 * @param date 日期Date
	 * @param pattern 格式
	 * @return 是/否
	 */
	public static boolean isValidDate(String date, String pattern)
	{
		try
		{
			DateUtils.convertDate(pattern, date);
			return true;
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 获取当前的时间戳
	 * @return 当前的时间戳
	 */
	public static Long getTimeStamp()
	{
		return System.currentTimeMillis();
	}

	/**
	 * 当前月剩余天数
	 * @param date 日期Date
	 * @param split 日期分隔符
	 * @return 剩余天数
	 */
	public static List<String> getSurplusDate(Date date, String split)
	{
		Calendar c = Calendar.getInstance();
		c.setTime(new Date());
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH) + 1;
		int day = c.get(Calendar.DATE);
		int maxday = c.getActualMaximum(Calendar.DAY_OF_MONTH);
		List<String> list = new ArrayList<String>();
		for (int i = 0; i <= maxday - day; i++)
		{
			int num = day + i;
			list.add(year + split + (month < 10 ? "0" + month : month) + split + (num < 10 ? "0" + num : num));
		}
		return list;
	}

	/**
	 * 获取当前日期月所指定的星期的所有日期
	 * @param date 日期Date
	 * @param week 星期数
	 * @return 日期List
	 */
	public static List<String> getDateByWeek(Date date, int week)
	{
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.DAY_OF_MONTH, 1);
		int day = c.getMaximum(Calendar.DAY_OF_MONTH);
		List<String> list = new ArrayList<String>();
		for (int i = 0; i < day; i++)
		{
			if (c.get(Calendar.DAY_OF_WEEK) == week)
			{
				list.add(formatDate(c.getTime(), null));
			}
			c.add(Calendar.DAY_OF_MONTH, 1);
		}
		return list;
	}

	/**
	 * 获得两个日期之间的所有天数，不包含开始和结束日期
	 * @param startDate 开始日期
	 * @param endDate 结束结束
	 * @return
	 * @throws ParseException
	 */
	public static List<String> getTimeDifference(String startDate, String endDate) throws ParseException
	{
		List<String> list = new ArrayList<String>();
		if (startDate.equals(endDate))
		{
			list.add(startDate);
			return list;
		}
		if (compareDate(endDate, startDate) == -1)
		{
			return null;
		}
		Date sDate = getDateFromShortString(startDate);
		Date eDate = getDateFromShortString(endDate);
		while (compareDate(sDate, eDate) == -1)
		{
			list.add(formatDate(sDate, null));
			sDate = addDay(sDate, 1);
		}
		list.remove(0);
		return list;
	}
}
